package com.winbomb.kingcard.utils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import android.util.Log;

import com.winbomb.kingcard.ICard;
import com.winbomb.kingcard.ICardPile;
import com.winbomb.kingcard.IGameLogic;
import com.winbomb.kingcard.IPlayer;
import com.winbomb.kingcard.Suit;
import com.winbomb.kingcard.base.Card;
import com.winbomb.kingcard.base.GameLogic;

public class GameUtils {

	private static final String TAG = "GameUtil";

	private static final Random rand = new Random();

	/**
	 * 获取Player在players中的坐标
	 * 
	 * 如果不存在，或者player为空，或者players为空，则返回-1
	 * 
	 * 如果存在多个，则返回最小的一个
	 * 
	 * @param players
	 * @param player
	 * @return
	 */
	public static int getPlayerIndex(IPlayer[] players, IPlayer target) {
		if (players == null || players.length == 0 || target == null) {
			return -1;
		}

		for (int i = 0; i < players.length; i++) {
			if (target == players[i]) {
				return i;
			}
		}

		return -1;
	}

	public static void coverCards(ICard[] cards) {
		for (ICard card : cards) {
			if (card != null) {
				card.setCovered(true);
			}
		}
	}

	/**
	 * 为一组牌同时设置上某一个标志
	 * 
	 * @param cards
	 * @param flag
	 */
	public static void setFlags(ICard[] cards, int flag) {
		for (ICard card : cards) {
			if (card != null) {
				card.setFlag(flag);
			}
		}
	}

	/**
	 * 测试一组牌中是否有一张有flag
	 * 
	 * @param cards
	 * @param flag
	 */
	public static boolean hasFlag(ICard[] cards, int flag) {
		for (ICard card : cards) {
			if (card != null && card.testFlag(flag)) {
				return true;
			}
		}

		return false;
	}

	/**
	 * 为某一组牌同时清理某个标志
	 * 
	 * @param cards
	 * @param flag
	 */
	public static void clearFlags(ICard[] cards, int flag) {
		for (ICard card : cards) {
			if (card != null) {
				card.clearFlag(flag);
			}
		}
	}

	/**
	 * 清除一组牌中的所有标志
	 * 
	 * @param cards
	 */
	public static void clearAllFlags(ICard[] cards) {
		for (ICard card : cards) {
			if (card != null) {
				card.clearAllFlags();
				card.clearAllSkills();
				card.setSelected(false);
				card.setCovered(false);
			}
		}
	}

	public static void clearAllFlags(List<ICard> cardList) {
		for (ICard card : cardList) {
			if (card != null) {
				card.clearAllFlags();
				card.clearAllSkills();
				card.setSelected(false);
				card.setCovered(false);
			}
		}
	}

	/**
	 * 随机从cards中选择一张card
	 * 
	 * @param cards
	 * @return
	 */
	public static ICard selectRandomCard(ICard[] cards) {

		int idx = rand.nextInt(cards.length);

		int i = idx;
		while (cards[i] == null) {
			i++;
			if (i >= cards.length) {
				i = 0;
			}

			// 已经转了一周了，都为null，防止死循环
			if (i == idx) {
				break;
			}
		}

		return cards[i];
	}

	/**
	 * 从cards里面随机选择cardCnt张牌
	 * 
	 * 返回的数组长度为cardCnt,如果cards的长度小于cardCnt,
	 * 
	 * 则大于cards长度后面的元素均为null.
	 * 
	 * @param cards
	 * @param cardCnt
	 * @return
	 */
	public static ICard[] selectRandomCard(ICard[] cards, int cardCnt) {

		if (cardCnt < 0) {
			throw new IllegalArgumentException();
		}

		List<ICard> tempList = Arrays.asList(cards);
		Collections.shuffle(tempList);

		ICard[] result = new ICard[cardCnt];
		for (int i = 0; i < result.length; i++) {
			result[i] = (i < tempList.size()) ? tempList.get(i) : null;
		}

		return result;
	}

	/**
	 * player1和player2是否是同一势力范围的，条件有三：
	 * 
	 * 1、player1 是 player2 下属
	 * 
	 * 2、player2 是 player1 的下属
	 * 
	 * 3、player1和player2有共同的Master(不为空）*
	 * 
	 * @param player1
	 * @param player2
	 * @return
	 */
	public static boolean isSameForce(IPlayer player1, IPlayer player2) {
		return !(player1.getMaster() != player2 && player2.getMaster() != player1 && player1.getMaster() != player2
				.getMaster());
	}

	/**
	 * 测试subord时不时master的下属
	 * 
	 * @param master
	 * @param subord
	 * @return
	 */
	public static boolean isSubord(IPlayer master, IPlayer subord) {
		return (subord.getMaster() == master || (!subord.isAlive() && subord.getMaster() == null));
	}

	/**
	 * 计算src玩家从左侧（顺时针方向）到dest玩家的距离，不计算已经灭亡的玩家
	 * 
	 * @param src
	 * @param dest
	 * @return
	 */
	public static int getLeftDistance(IPlayer src, IPlayer dest) {
		return getDistance(src, dest, false, false, false);
	}

	/**
	 * 计算src玩家从右侧（逆时针方向）到dest玩家的距离，不计算已经灭亡的玩家
	 * 
	 * @param src
	 * @param dest
	 * @return
	 */
	public static int getRightDistance(IPlayer src, IPlayer dest) {
		return getDistance(src, dest, true, false, false);
	}

	/**
	 * 计算src玩家从左侧（顺时针方向）到dest玩家的攻击距离，所谓攻击距离，即去除灭亡玩家和
	 * 
	 * 己方势力之后的距离。
	 * 
	 * @param src
	 * @param dest
	 * @return
	 */
	public static int getLeftAtkDistance(IPlayer src, IPlayer dest) {
		return getDistance(src, dest, false, false, true);
	}

	/**
	 * 计算src玩家从右侧（逆时针方向）到dest玩家的攻击距离
	 * 
	 * @param src
	 * @param dest
	 * @return
	 */
	public static int getRightAtkDistance(IPlayer src, IPlayer dest) {
		return getDistance(src, dest, true, false, true);
	}

	/**
	 * 获取两个玩家之间的距离
	 * 
	 * @param src
	 * @param dest
	 * @param dir
	 *            方向
	 * @param calcDeath
	 *            是否计算灭亡的势力
	 * @param isAtkDis
	 *            是否是计算攻击距离(攻击距离不计算同势力)
	 * @return
	 */
	private static int getDistance(IPlayer src, IPlayer dest, boolean dir, boolean calcDeath, boolean isAtkDis) {

		if (src == dest) {
			return 0;
		}

		int dist = 0;
		IPlayer nextTarget = src;
		do {
			nextTarget = (dir) ? nextTarget.getRightPlayer() : nextTarget.getLeftPlayer();
			if (!nextTarget.isAlive() && !calcDeath) {
				continue;
			}
			if (isAtkDis && isSameForce(src, nextTarget)) {
				continue;
			}

			dist++;

		} while (nextTarget != dest && nextTarget != src);

		/** 找了一圈也没找到dest，返回-1表示不可达 */
		if (nextTarget == src) {
			return -1;
		}

		return dist;
	}

	/**
	 * 一个牌的数组中是否包含某一张特定的牌
	 * 
	 * @param cards
	 * @param tgCard
	 * @return
	 */
	public static int getCardIndex(ICard[] cards, ICard tgCard) {
		for (int i = 0; i < cards.length; i++) {
			if (cards[i] == tgCard) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * 交换Cards中两个元素的位置
	 * 
	 * @param cards
	 * @param i
	 * @param j
	 */
	public static void swapCards(ICard[] cards, int i, int j) {
		if (i == j) {
			return;
		}

		if (i < 0 || j < 0 || i > cards.length || j > cards.length) {
			Log.w(TAG, "illegal parameter.");
		}

		ICard temp = cards[i];
		cards[i] = cards[j];
		cards[j] = temp;
	}

	/**
	 * 打乱某一组牌的顺序
	 * 
	 * 这里是简单地做10次交换
	 * 
	 * @param cards
	 */
	public static void shuffleCards(ICard[] cards) {
		for (int i = 0; i < 10; i++) {
			int srcIdx = rand.nextInt(cards.length);
			int destIdx = rand.nextInt(cards.length);
			swapCards(cards, srcIdx, destIdx);
		}
	}

	/**
	 * 攻击卡片是否能够成功攻击被攻击卡片
	 * 
	 * @param atkCards
	 *            攻击卡片
	 * @param atkIdx
	 *            发动进攻的卡片坐标
	 * @param tgCard
	 *            被攻击卡片
	 * @param tgIdx
	 *            被攻击卡片的坐标
	 * @return
	 */
	public static boolean isAttackSuccess(ICard[] atkCards, int atkIdx, ICard[] tgCards, int tgIdx) {

		// 首先判断是否在攻击距离之内
		ICard atkCard = atkCards[atkIdx];
		boolean inAtkRange = isInAtkRange(atkCards, atkIdx, tgIdx);

		// 如果不在攻击范围之内,则返回false
		if (!inAtkRange) {
			return false;
		}

		return atkCard.canBeat(tgCards[tgIdx]);
	}

	/**
	 * 检查是否在攻击范围之内
	 * 
	 * @param atkCards
	 * @param atkIdx
	 * @param tgIdx
	 * @return
	 */
	public static boolean isInAtkRange(ICard[] atkCards, int atkIdx, int tgIdx) {

		ICard atkCard = atkCards[atkIdx];
		boolean inAtkRange = true;
		if (!isInAtkRange(atkIdx, tgIdx, atkCard)) {

			inAtkRange = false;
			// 检查左右两侧是否有相同花色的牌可以扩展攻击距离.此处体现了连诛技能的作用
			for (int i = atkIdx - 1; i >= 0 && !inAtkRange; i--) {
				if (atkCards[i] == null || atkCards[i].testFlag(Card.IS_DEFEATED)
						|| atkCards[i].testFlag(Card.IS_UNOPEN_CARD) || atkCards[i].getSuit() != atkCard.getSuit()) {
					break;
				}
				if (isInAtkRange(i, tgIdx, atkCards[i])) {
					inAtkRange = true;
				}
			}
			for (int i = atkIdx + 1; i < atkCards.length && !inAtkRange; i++) {
				if (atkCards[i] == null || atkCards[i].testFlag(Card.IS_DEFEATED)
						|| atkCards[i].testFlag(Card.IS_UNOPEN_CARD) || atkCards[i].getSuit() != atkCard.getSuit()) {
					break;
				}
				if (isInAtkRange(i, tgIdx, atkCards[i])) {
					inAtkRange = true;
				}
			}

			// 检查是否有相同点数的牌可以扩展攻击距离
			for (int i = 0; i < atkCards.length && !inAtkRange; i++) {
				if (atkCards[i] == null || atkCards[i].testFlag(Card.IS_DEFEATED)
						|| atkCards[i].testFlag(Card.IS_UNOPEN_CARD) || atkCards[i].getPoint() != atkCard.getPoint()) {
					continue;
				}

				if (isInAtkRange(i, tgIdx, atkCards[i])) {
					inAtkRange = true;
				}

			}
		}

		return inAtkRange;
	}

	public static boolean isInAtkRange(int atkIdx, int tgIdx, ICard card) {

		int dis = atkIdx - tgIdx;
		// 如果是王牌或者士牌(大王/小王/2/A),攻击范围是左右各2张
		if (card.isBlackJoker() || card.isRedJoker() || card.getPoint() == 1 || card.getPoint() == 2) {
			return (dis <= 2 && dis >= -2);
		}

		// 如果是将牌或兵牌,攻击范围要根据花色确定
		Suit suit = card.getSuit();
		if (suit == Suit.SPADE) {
			// 黑桃只能攻击前面三格之内的牌
			return (dis >= 0 && dis < 3);

		} else if (suit == Suit.HEART) {
			// 红桃只能攻击后面三格之内的牌
			return (dis <= 0 && dis > -3);

		} else if (suit == Suit.CLUB) {
			// 梅花只能攻击与自己距离大于等于2的格子
			return (dis <= -2 || dis >= 2);

		} else if (suit == Suit.DIAMOND) {
			// 方块只能攻击自己及左右两边各一格
			return (dis <= 1 && dis >= -1);

		} else {
			Log.w(TAG, "Invalid card :" + card);
			return false;
		}
	}

	/**
	 * 统计cards里面还有多少存活的牌(即指没有被击败且不为null)
	 * 
	 * @param cards
	 * @return
	 */
	public static int getLiveCardCount(ICard[] cards) {
		int count = 0;
		for (ICard card : cards) {
			if (card != null && !card.testFlag(Card.IS_DEFEATED)) {
				count++;
			}
		}

		return count;
	}

	/**
	 * 统计剩余的活牌加起来还剩多少点
	 * 
	 * @param cards
	 * @return
	 */
	public static int getLeftCardPoint(ICard[] cards) {
		int point = 0;
		for (ICard card : cards) {
			if (card != null && !card.testFlag(Card.IS_DEFEATED)) {
				point += card.getPoint();
			}
		}

		return point;
	}

	/**
	 * 刷新卡片的"连诛"技能标记
	 * 
	 * @param cards
	 */
	public static void refreshSkillFlags(ICard[] cards) {

		// 清除之前的技能标记
		for (ICard card : cards) {
			if (card != null) {
				card.removeSkill(Card.SKILL_CHEER_UP);
				card.removeSkill(Card.SKILL_ROW_KILLER);
			}
		}

		// 刷新鼓舞标记, 如果牌面上有同花色的将领,则该牌受鼓舞
		for (ICard card : cards) {
			if (card == null || (!card.testFlag(Card.IS_ATK_CARD) && !card.testFlag(Card.IS_UNOPEN_CARD))) {
				continue;
			}

			// 只有兵牌和将牌可以被鼓舞, 王牌和士牌无法被鼓舞.
			if (card.getPoint() > 13 || card.getPoint() <= 2) {
				continue;
			}

			// 查找有没有该花色的将牌
			for (ICard tgCard : cards) {
				if (tgCard == null || tgCard == card || tgCard.getPoint() <= 10 || tgCard.testFlag(Card.IS_DEFEATED)
						|| tgCard.testFlag(Card.IS_UNOPEN_CARD)) {
					continue;
				}

				// 如果这张牌的花色和将牌花色相同,则被鼓舞.
				// 如果将牌是王,则同颜色即被鼓舞.
				boolean isKing = (tgCard.isBlackJoker() || tgCard.isRedJoker());
				Suit tgSuit = tgCard.getSuit();
				Suit suit = card.getSuit();
				if ((isKing && suit.isSameColor(tgSuit)) || (suit == tgSuit)) {
					card.addSkill(Card.SKILL_CHEER_UP);
					break;
				}

			}
		}

		// 刷新连诛技能
		for (int i = 0; i < cards.length; i++) {
			if (cards[i] == null || cards[i].testFlag(Card.IS_DEFEATED) || cards[i].testFlag(Card.IS_UNOPEN_CARD)) {
				continue;
			}

			int j = i + 1;
			while (j < cards.length && cards[j] != null && !cards[j].testFlag(Card.IS_DEFEATED)
					&& !cards[j].testFlag(Card.IS_UNOPEN_CARD) && cards[j].getSuit() == cards[i].getSuit()) {
				j++;
			}

			int dis = j - i;
			String skillName = (dis >= 2) ? Card.SKILL_ROW_KILLER : null;

			for (int k = i; k < j; k++) {
				cards[k].addSkill(skillName);
			}
			i = j;
		}

		// 点数一样也可以连诛
		for (int i = 0; i < cards.length; i++) {
			if (cards[i] == null || cards[i].testFlag(Card.IS_DEFEATED) || cards[i].testFlag(Card.IS_UNOPEN_CARD)) {
				continue;
			}

			for (int j = i + 1; j < cards.length; j++) {
				if (cards[j] == null || cards[j].testFlag(Card.IS_DEFEATED) || cards[j].testFlag(Card.IS_UNOPEN_CARD)) {
					continue;
				}

				if (cards[j].getPoint() == cards[i].getPoint()) {
					cards[i].addSkill(Card.SKILL_ROW_KILLER);
					cards[j].addSkill(Card.SKILL_ROW_KILLER);
				}
			}
		}
	}

	public static int removeDefeatCards(ICard[] cards) {
		int count = 0;
		for (int i = 0; i < cards.length; i++) {
			if (cards[i] != null && cards[i].testFlag(Card.IS_DEFEATED)) {
				cards[i] = null;
				count++;
			}
		}
		return count;
	}

	public static int removeDefeatCards(List<ICard> cards) {
		int count = 0;

		// 迭代删除掉所有null或者被击败的牌
		Iterator<ICard> it = cards.iterator();
		while (it.hasNext()) {
			ICard card = it.next();
			if (card == null || card.testFlag(Card.IS_DEFEATED)) {
				it.remove();
				count++;
			}
		}

		return count;
	}

	/**
	 * 获取剩余势力的数量
	 * 
	 * 当势力的master为自己的时候,我们算他为一个势力.
	 * 
	 * @param players
	 * @return
	 */
	public static int getMasterCount(IPlayer[] players) {
		int count = 0;
		for (IPlayer player : players) {
			if (player != null && player.getMaster() == player) {
				count++;
			}
		}

		return count;
	}

	public static int evaluate(ICard[] cards) {
		return cards.length * 100;
	}

	/**
	 * 检查有几张牌(其实就是去掉为null的个数)
	 * 
	 * @param cards
	 * @return
	 */
	public static int countCards(ICard[] cards) {

		int count = 0;
		for (ICard card : cards) {
			if (card != null) {
				count++;
			}
		}

		return count;
	}

	/**
	 * 检查有几张选中的牌
	 * 
	 * @param cards
	 * @return
	 */
	public static int countSelectedCards(ICard[] cards) {
		int count = 0;
		for (ICard card : cards) {
			if (card != null && card.isSelected()) {
				count++;
			}
		}

		return count;
	}

	public static int countSelectedCards(List<ICard> cards) {
		int count = 0;
		for (ICard card : cards) {
			if (card != null && card.isSelected()) {
				count++;
			}
		}

		return count;
	}

	/**
	 * 获得下一个座位号
	 * 
	 * @param seatNum
	 * @param isClockwise
	 * @return
	 */
	public static int getNextSeatNum(int seatNum, boolean isClockwise) {
		int nextSeat = (isClockwise) ? seatNum - 1 : seatNum + 1;
		if (nextSeat < 0) {
			nextSeat = GameLogic.MAX_PLAYER_COUNT - 1;
		} else if (nextSeat >= GameLogic.MAX_PLAYER_COUNT) {
			nextSeat = 0;
		}

		return nextSeat;
	}

	/**
	 * 检查牌的一致性,看程序中是否存在问题
	 * 
	 * @param game
	 * @return
	 */
	public static boolean checkConsistance(IGameLogic game) {

		int[][] cardCnts = new int[13][6];

		// 先统计手牌
		for (IPlayer player : game.getPlayers()) {
			for (ICard card : player.getCards()) {
				int col = card.getPoint();
				col = (col >= 14) ? 0 : col - 1;
				int row = card.getSuit().ordinal();

				cardCnts[col][row]++;
			}

			for (ICard card : player.getBattleCards()) {
				int col = card.getPoint();
				col = (col >= 14) ? 0 : col - 1;
				int row = card.getSuit().ordinal();

				cardCnts[col][row]++;
			}
		}

		// 统计牌堆的牌
		ICardPile cardPile = game.getCardPile();
		for (ICard card : cardPile.getDrawCards()) {
			int col = card.getPoint();
			col = (col >= 14) ? 0 : col - 1;
			int row = card.getSuit().ordinal();

			cardCnts[col][row]++;
		}

		for (ICard card : cardPile.getDiscardCards()) {
			int col = card.getPoint();
			col = (col >= 14) ? 0 : col - 1;
			int row = card.getSuit().ordinal();

			cardCnts[col][row]++;
		}

		// 检查
		for (int i = 0; i < 13; i++) {
			for (int j = 0; j < 4; j++) {
				if (cardCnts[i][j] != 3) {
					return false;
				}
			}
		}

		if (cardCnts[4][0] != 3 || cardCnts[5][0] != 3) {
			return false;
		}

		return true;
	}
}
